﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Segex
{
    public class SegexGeneratorOutput
    {
        public string Result { get; set; }
        public string Preprocessor { get; set; }
        public string Output { get; set; }
        public bool IsError { get; set; }
    }

    public class SegexGenerator
    {
        private MemoryStream scannerStream;
        private PreProcessor preProcessor;



        public SegexGenerator()
        {
            preProcessor = new PreProcessor();
        }

        public SegexGeneratorOutput Generate(string input)
        {
            Scanner lexer;
            Parser parser;

            //1) Preprocess input
            string i = preProcessor.Preprocess(input);

            //2) Load into stream for the lexer / scanner.
            using (Stream stream = LoadScannerStream(i))
            {
                //3) Trigger parser to generate us a Regex. Need to investigate why this holds state and add some reset functions.
                lexer = new Scanner(stream);
                parser = new Parser(lexer);
                parser.Parse();
            }

            //Extract resulting insructions and combine into a single result.
            StringBuilder sb = new StringBuilder();
            foreach (string s in parser.Instructions)
                sb.Append(s);

            //Tally errors //TODO: tidy up this
            int errorCount = parser.errors.count;
            string errorText = parser.errors.errors.ToString() + Environment.NewLine;
            errorText += "Generated " + parser.Instructions.Count + " instructions.";


            //Return what we have
            SegexGeneratorOutput lo = new SegexGeneratorOutput()
            {
                Result = sb.ToString(),
                IsError = errorCount > 0,
                
                Output = errorText,
                Preprocessor = i
            };



            return lo;

        }

        /// <summary>
        /// Load data into the memory stream used by the scanner / lexer
        /// </summary>
        /// <param name="data">The pre-processed data to load</param>
        private Stream LoadScannerStream(string data)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter sw = new StreamWriter(stream, Encoding.UTF8, 1024, true);
            sw.Write(data);
            sw.Flush();
            stream.Position = 0;
            return stream;
        }

    }
}
